package com.yanqu.road.server.gameplayer.module.activity.ghost;

import com.yanqu.road.entity.activity.ActivityInfo;
import com.yanqu.road.entity.activity.ghost.GhostPatrons;
import com.yanqu.road.entity.activity.ghost.GhostUserData;
import com.yanqu.road.entity.activity.ghost.config.GhostBossConfig;
import com.yanqu.road.entity.activity.ghost.config.GhostBoxConfig;
import com.yanqu.road.entity.activity.ghost.config.GhostConfig;
import com.yanqu.road.entity.activity.seasontask.SeasonTaskConditionData;
import com.yanqu.road.entity.config.goods.OpenGoodsBagResult;
import com.yanqu.road.entity.config.skill.SkillInfo;
import com.yanqu.road.entity.enums.*;
import com.yanqu.road.entity.log.LogGhostAttack;
import com.yanqu.road.entity.log.LogGhostBox;
import com.yanqu.road.entity.log.LogGhostBuyBuff;
import com.yanqu.road.entity.log.LogGhostDisperse;
import com.yanqu.road.entity.log.LogGhostExplore;
import com.yanqu.road.entity.log.LogGhostGuess;
import com.yanqu.road.entity.log.LogGhostToken;
import com.yanqu.road.entity.player.UserPatrons;
import com.yanqu.road.entity.player.UserPatronsSkill;
import com.yanqu.road.entity.player.UserVehicle;
import com.yanqu.road.entity.task.args.UnionRiseRankArgs;
import com.yanqu.road.logic.bussiness.activity.GhostActivityBusiness;
import com.yanqu.road.logic.config.GameConfig;
import com.yanqu.road.logic.helper.CalcPowerResult;
import com.yanqu.road.logic.helper.PowerHelper;
import com.yanqu.road.pb.activity.GhostActivityProto;
import com.yanqu.road.pb.worldmessage.WorldMessageProto;
import com.yanqu.road.server.gameplayer.GamePlayer;
import com.yanqu.road.server.gameplayer.module.base.GeneralModule;
import com.yanqu.road.server.gameplayer.module.patrons.PatronsModule;
import com.yanqu.road.server.gameplayer.module.player.CurrencyModule;
import com.yanqu.road.server.gameplayer.module.player.PreReduceModule;
import com.yanqu.road.server.gameplayer.module.vehicle.VehicleModule;
import com.yanqu.road.server.manger.activity.ActivityMgr;
import com.yanqu.road.server.manger.activity.curio.CurioMgr;
import com.yanqu.road.server.manger.activity.ghost.GhostMgr;
import com.yanqu.road.server.manger.activity.ghost.GhostSceneLogic;
import com.yanqu.road.server.manger.config.GoodsBagMgr;
import com.yanqu.road.server.manger.config.SkillMgr;
import com.yanqu.road.server.manger.config.SystemOpenMgr;
import com.yanqu.road.server.manger.log.AutoLogMgr;
import com.yanqu.road.server.manger.log.LogMgr;
import com.yanqu.road.server.manger.player.WorldMessageMgr;
import com.yanqu.road.server.pb.GhostPb;
import com.yanqu.road.server.pb.PlayerPb;
import com.yanqu.road.server.pb.WorldMessagePb;
import com.yanqu.road.server.protocol.ClientProtocol;
import com.yanqu.road.server.protocol.CrossProtocol;
import com.yanqu.road.server.protocol.GameErrorCode;
import com.yanqu.road.utils.LocalDateTimeHelper;
import com.yanqu.road.utils.RandomHelper;
import com.yanqu.road.utils.property.Property;
import com.yanqu.road.utils.property.PropertyHelper;
import com.yanqu.road.utils.string.StringUtils;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.ConcurrentHashMap;

public class GhostModule extends GeneralModule {

    private GhostUserData userData;

    public GhostModule(GamePlayer player) {
        super(player);
    }

    @Override
    public boolean loadData() {
        ActivityInfo activityInfo = GhostMgr.getActivityInfo();
        if (ActivityMgr.activityInShowTime(activityInfo)) {
            userData = GhostActivityBusiness.getGhostUserData(activityInfo.getActivityId(), player.getUserId());
            initUserData();
        }
        return true;
    }

    @Override
    public boolean afterLoadData() {
        return true;
    }

    @Override
    public boolean saveData() {
        if (userData != null) {
            if (userData.isInsertOption()) {
                GhostActivityBusiness.addGhostUserData(userData);
            } else if (userData.isUpdateOption()) {
                GhostActivityBusiness.updateGhostUserData(userData);
            }
        }
        return true;
    }

    @Override
    public void afterLogin() {
        GhostConfig ghostConfig = GhostMgr.getGhostConfig();
        if (ghostConfig != null && ActivityMgr.activityInShowTime(ghostConfig.getActivityInfo())) {
            syncGhostConfig();
            initUserData();
            checkUserData();
            syncGhostUserData();
            // 清空部分预扣除
            if (userData != null) {
                userData.setPreReduceEnergy(0);
            }
        }
    }

    public void syncGhostConfig() {
        GhostConfig ghostConfig = GhostMgr.getGhostConfig();
        if (ghostConfig != null && ActivityMgr.activityInShowTime(ghostConfig.getActivityInfo())) {
            GhostActivityProto.SyncGameConfigRespMsg.Builder configRespMsg = GhostPb.parseSyncGameConfigRespMsg(ghostConfig);
            player.sendPacket(ClientProtocol.U_GHOST_SYNC_CONFIG, configRespMsg);

            // 跨服拿其他配置
            GhostActivityProto.CrossGhostGetBossConfigReqMsg.Builder builder = GhostActivityProto.CrossGhostGetBossConfigReqMsg.newBuilder();
            builder.setActivityId(ghostConfig.getActivityId());
            builder.setServerId(player.getUserInfo().getOriginalServerId());
            player.sendPacket(CrossProtocol.C2_GHOST_ACTIVITY_GET_CONFIG, builder);
        }
    }

    public void syncGhostUserData() {
        if (userData == null) {
            return;
        }
        GhostActivityProto.CrossGetGhostGameDataReqMsg.Builder builder = GhostActivityProto.CrossGetGhostGameDataReqMsg.newBuilder();
        builder.setActivityId(userData.getActivityId());
        builder.setServerId(player.getUserInfo().getOriginalServerId());
        builder.setUserData(GhostPb.parseGhostUserDataMsg(userData));
        builder.setNeedErrorCode(false);
        player.sendPacket(CrossProtocol.C2_GHOST_ACTIVITY_GET_GAME_DATA, builder);
    }

    public synchronized void initUserData() {
        // 系统未解锁
        if (!SystemOpenMgr.systemOpen(player, eSystemId.GhostActivity.getValue())) {
            return;
        }
        // 没有活动
        ActivityInfo activityInfo = GhostMgr.getActivityInfo();
        if (!ActivityMgr.activityInShowTime(activityInfo)) {
            return;
        }
        // 已经有数据了
        if (userData != null && userData.getActivityId() == activityInfo.getActivityId()) {
            return;
        }

        userData = new GhostUserData();
        userData.setActivityId(activityInfo.getActivityId());
        userData.setUserId(player.getUserId());
        userData.setEnergy(GhostMgr.getGhostConfig().getMaxEnergy());
        userData.setLastRecoveryTime(System.currentTimeMillis());
        userData.setEvent(0, "", System.currentTimeMillis());
        userData.setComplete(true);
        userData.setGetDisperse(false);
        userData.setBuffLevel(0);
        userData.setScore(0);
        userData.setAttackMap(new ConcurrentHashMap<>());
        userData.setBuyEnergyTimes(0);
        userData.setGetCleanDisperse(false);
        userData.setInsertOption();
    }

    /**
     * 检查数据（体力恢复、每日重置）
     */
    public void checkUserData() {
        GhostConfig ghostConfig = GhostMgr.getGhostConfig();
        if (userData != null && ghostConfig != null && ActivityMgr.activityInTime(ghostConfig.getActivityInfo())) {
            // 重置
            long lastResetTime = GhostMgr.calLastResetTime();
            if (userData.getResetTime() != lastResetTime && userData.getResetTime() < lastResetTime) {

                userData.setComplete(true);
                userData.setEvent(0, "", System.currentTimeMillis());

                userData.setBuffLevel(0);
                userData.setEnergy(ghostConfig.getMaxEnergy());
                userData.setGetDisperse(false);
                userData.setAttackMap(new ConcurrentHashMap<>());
                userData.setBuyEnergyTimes(0);
                userData.setGetCleanDisperse(false);

                userData.setLastRecoveryTime(lastResetTime);
                userData.setResetTime(lastResetTime);

                userData.setExploreTimes(0);
            }
            // 体力恢复
            CalcPowerResult calcPowerResult = PowerHelper.calcPower(userData.getLastRecoveryTime() / 1000, ghostConfig.getEnergyRecoveryTime() / 1000, 1, ghostConfig.getMaxEnergy(), userData.getEnergy());
            userData.setEnergy(calcPowerResult.getCurPower());
            userData.setLastRecoveryTime(calcPowerResult.getLastRecoverTime() * 1000);
        }
    }

    /**
     * 获取用户数据
     */
    public GhostUserData getUserData() {
        checkUserData();
        return userData;
    }

    /**
     * 升级buff
     */
    public int upgradeAttackBuff() {

        GhostConfig ghostConfig = GhostMgr.getGhostConfig();
        if (ghostConfig.getAttackBuffSwitch() != 1) {
            return GameErrorCode.E_GHOST_ACTIVITY_FUNCTION_NO_OPEN;
        }

        String upgradeCost = GhostMgr.getAttackBuffUpgradeCost(userData.getBuffLevel() + 1);
        if (upgradeCost == null) {
            return GameErrorCode.E_GHOST_ACTIVITY_CAN_NOT_UPGRADE_BUFF;
        }
        Property property = PropertyHelper.parseStringToProperty(upgradeCost);
        if (!player.getModule(CurrencyModule.class).removeCurrency(property, eLogMoneyType.Ghost, eLogMoneyType.GhostUpgradeBuffCost)) {
            return GameErrorCode.E_GHOST_ACTIVITY_ITEM_NO_ENOUGH;
        }

        userData.setBuffLevel(userData.getBuffLevel() + 1);

        // 日志
        AutoLogMgr.add(new LogGhostBuyBuff(
                ghostConfig.getActivityId(),
                player.getUserId(),
                upgradeCost,
                userData.getBuffLevel()
        ));

        return 0;
    }

    /**
     * 体力是否足够
     */
    public boolean energyIsEnough() {
        if (userData == null) {
            return false;
        }
        return userData.getEnergy() - userData.getPreReduceEnergy() > 0;
    }

    /**
     * 预扣除体力
     */
    public void preReduceEnergy() {
        if (userData == null) {
            return;
        }
        userData.setPreReduceEnergy(userData.getPreReduceEnergy() + 1);
    }

    /**
     * 恢复预扣除体力
     */
    public void restorePreReduceEnergy() {
        if (userData == null) {
            return;
        }
        userData.setPreReduceEnergy(userData.getPreReduceEnergy() - 1);
    }

    /**
     * 减少体力
     */
    public void reduceEnergy() {
        boolean beforeBigThanMax = userData.getEnergy() >= GhostMgr.getGhostConfig().getMaxEnergy();
        userData.setEnergy(userData.getEnergy() - 1);
        boolean afterSmallThanMax = userData.getEnergy() < GhostMgr.getGhostConfig().getMaxEnergy();
        if (beforeBigThanMax && afterSmallThanMax) {
            userData.setLastRecoveryTime(System.currentTimeMillis());
        }
    }

    /**
     * 购买体力
     */
    public int buyEnergy(int times) {
        if (times <= 0) {
            return GameErrorCode.E_ERROR_PARAMETER;
        }
        GhostConfig ghostConfig = GhostMgr.getGhostConfig();

        int getCount = ghostConfig.getBuyEnergyGetCount() * times;
        int costIngotsCount = 0;

        int hadBuyTimes = userData.getBuyEnergyTimes();
        for (int i = 0; i < times; i++) {
            // 本次消耗元宝数量 = 基础消耗数量 + 递增数量 * 递增次数
            int curCost = ghostConfig.getBuyEnergyBaseIngots() + ghostConfig.getBuyEnergyIncrIngots() * (i + hadBuyTimes);
            costIngotsCount += curCost;
        }

        Property property = new Property();
        property.addProperty(GameConfig.GAME_MONEY_INGOTS, BigInteger.valueOf(costIngotsCount));

        if (!player.getModule(CurrencyModule.class).removeCurrency(property, eLogMoneyType.Ghost, eLogMoneyType.GhostBuyEnergyCost)) {
            return GameErrorCode.E_GHOST_ACTIVITY_ITEM_NO_ENOUGH;
        }

        userData.setEnergy(userData.getEnergy() + getCount);
        userData.setBuyEnergyTimes(userData.getBuyEnergyTimes() + times);
        return 0;
    }

    /**
     * 探索
     */
    public int explore() {

        if (userData == null) {
            return GameErrorCode.E_GHOST_ACTIVITY_NO_UNLOCK;
        }

        if (!userData.isComplete()) {
            return GameErrorCode.E_GHOST_ACTIVITY_EVENT_NO_COMPLETE;
        }

        if (!energyIsEnough()) {
            return GameErrorCode.E_GHOST_ACTIVITY_ENERGY_NO_ENOUGH;
        }

        // 防止频繁操作
        long now = System.currentTimeMillis();
        if (now - userData.getLastExploreTime() < GameConfig.GHOST_EXPLORE_INTERVAL) {
            return GameErrorCode.E_GHOST_ACTIVITY_REQUEST_FREQUENTLY;
        }
        userData.setLastExploreTime(now);

        // 预扣除体力
        preReduceEnergy();

        GhostActivityProto.CrossExploreReqMsg.Builder builder = GhostActivityProto.CrossExploreReqMsg.newBuilder();
        builder.setActivityId(userData.getActivityId());
        builder.setUserId(player.getUserId());
        builder.setPlayer(PlayerPb.parsePlayerBaseTempMsg(player.getUserInfo()));
        builder.setUserResetTime(userData.getResetTime());
        builder.setExploreTimes(userData.getExploreTimes());
        player.sendPacket(CrossProtocol.C2_GHOST_ACTIVITY_CROSS_EXPLORE, builder);
        return 0;
    }

    /**
     * 处理跨服返回探索结果
     */
    public int exploreFromCross(int ret, int eventType, String param, GhostActivityProto.TodayGhostDataMsg todayGhostDataMsg, long userResetTime) {

        // 恢复预扣除
        restorePreReduceEnergy();

        if (ret == 0) {

            if (userData.getResetTime() != userResetTime) {
                return GameErrorCode.E_GHOST_ACTIVITY_REFRESH;
            }

            GhostConfig ghostConfig = GhostMgr.getGhostConfig();
            if (ghostConfig == null) {
                return GameErrorCode.E_GHOST_ACTIVITY_NO_OPEN;
            }

            // 设置前多校验一下
            if (eventType <= 0 || eventType >= 4 || StringUtils.isNullOrEmpty(param)) {
                return GameErrorCode.E_GHOST_ACTIVITY_NO_OPEN;
            }
            if (!userData.isComplete()) {
                return GameErrorCode.E_GHOST_ACTIVITY_EVENT_NO_COMPLETE;
            }

            // Boss事件特殊处理
            boolean firstFindBig = false; // 是否【第一个发现】活阎王
            boolean bigBoss = false; // 是否活阎王
            if (eventType == 1) {
                List<Integer> integerList = StringUtils.stringToIntegerList(param, "\\|");
                param = integerList.get(0) + "|" + integerList.get(1);
                firstFindBig = integerList.get(2) == 1;
                bigBoss = integerList.get(3) == 1;
            }

            // 扣体力
            reduceEnergy();
            SeasonTaskConditionData data = new SeasonTaskConditionData(BigInteger.valueOf((long)GhostMgr.getActivityInfo().getType()), BigInteger.ONE);
            player.notifyListener(eGamePlayerEventType.GhostCostStaminaTask.getValue(), data);

            // 设置新事件
            userData.setEvent(eventType, param, System.currentTimeMillis());
            userData.setComplete(false);

            // 修改探索次数
            userData.setExploreTimes(bigBoss ? 0 : userData.getExploreTimes() + 1);

            // 加奖励
            int exploreGetTokenCount = ghostConfig.getExploreGetTokenCount();
            userData.setTokenCount(userData.getTokenCount() + exploreGetTokenCount);
            player.notifyListener(eGamePlayerEventType.GhostTokenCount.getValue(), userData.getTokenCount());

            // 返回
            GhostActivityProto.ExploreRespMsg.Builder builder = GhostActivityProto.ExploreRespMsg.newBuilder();
            builder.setRet(0);
            builder.setIsBigBoss(firstFindBig);
            builder.setTodayGhostData(todayGhostDataMsg);
            builder.setUserData(GhostPb.parseGhostUserDataMsg(userData));
            player.sendPacket(ClientProtocol.U_GHOST_EXPLORE, builder);


            // 日志
            AutoLogMgr.add(new LogGhostExplore(
                    ghostConfig.getActivityId(),
                    player.getUserId(),
                    userData.getEventType(),
                    userData.getParam()
            ));

        }

        return ret;

    }

    /**
     * 跳过事件
     */
    public int skipEvent() {

        if (userData == null) {
            return GameErrorCode.E_GHOST_ACTIVITY_NO_UNLOCK;
        }

        boolean oldIsComplete = userData.isComplete();

        userData.setComplete(true);

        // 事件没完成跳过才要记录跳过日志
        if (!oldIsComplete) {
            GhostConfig ghostConfig = GhostMgr.getGhostConfig();
            if (userData.getEventType() == 2) {
                List<Integer> integerList = StringUtils.stringToIntegerList(userData.getParam(), "\\|");
                int boxItemId = integerList.get(1);

                String openCost = "";
                for (GhostBoxConfig boxConfig : ghostConfig.getBoxConfigList()) {
                    if (boxItemId == boxConfig.getBoxItemId()) {
                        openCost = boxConfig.getOpenCost();
                        break;
                    }
                }

                String unionUid = player.getUserInfo().getUnionUid();
                // 必须是有消耗的才能共享给商会
                if (!StringUtils.isNullOrEmpty(unionUid) && !StringUtils.isNullOrEmpty(openCost) && !"0".equals(openCost)) {
                    GhostActivityProto.CrossSkipBoxEventReqMsg.Builder builder = GhostActivityProto.CrossSkipBoxEventReqMsg.newBuilder();
                    builder.setActivityId(ghostConfig.getActivityId());
                    builder.setServerId(player.getUserInfo().getOriginalServerId());
                    builder.setBoxId(boxItemId);
                    builder.setUnionId(unionUid);
                    player.sendPacket(CrossProtocol.C2_GHOST_ACTIVITY_SKIP_BOX_EVENT, builder);
                    log.warn("玩家{}放弃宝箱，共享给商会了", player.getUserId());
                }
                // 日志
                AutoLogMgr.add(new LogGhostBox(
                        ghostConfig.getActivityId(),
                        player.getUserId(),
                        boxItemId,
                        openCost,
                        false,
                        ""
                ));
            } else if (userData.getEventType() == 3) {
                // 日志
                AutoLogMgr.add(new LogGhostGuess(
                        ghostConfig.getActivityId(),
                        player.getUserId(),
                        userData.getParam(),
                        false,
                        false
                ));
            }
        }

        return 0;
    }



    /**
     * 处理货箱事件（无数量、过期时间）
     */
    public int newHandleBoxEvent() {

        if (userData == null) {
            return GameErrorCode.E_GHOST_ACTIVITY_NO_UNLOCK;
        }
        if (userData.isComplete()) {
            return GameErrorCode.E_GHOST_ACTIVITY_EVENT_HAD_COMPLETE;
        }
        if (userData.getEventType() != 2) {
            return GameErrorCode.E_GHOST_ACTIVITY_EVENT_ERROR;
        }
        GhostConfig ghostConfig = GhostMgr.getGhostConfig();

        List<Integer> integerList = StringUtils.stringToIntegerList(userData.getParam(), "\\|");
        int boxItemId = integerList.get(1);

        String openCost = "";
        for (GhostBoxConfig boxConfig : ghostConfig.getBoxConfigList()) {
            if (boxItemId == boxConfig.getBoxItemId()) {
                openCost = boxConfig.getOpenCost();
                break;
            }
        }
        if (StringUtils.isNullOrEmpty(openCost)) {
            log.error("GhostModule open box error! can not find cost! had skip event! userId={}, eventParam={}", player.getUserId(), userData.getParam());
            userData.setComplete(true);
            return GameErrorCode.E_GHOST_ACTIVITY_EVENT_HAD_COMPLETE;
        }

        // 扣道具
        if (!openCost.equals("0")) {
            Property costProp = PropertyHelper.parseStringToProperty(openCost);
            if (!player.getModule(CurrencyModule.class).removeCurrency(costProp, eLogMoneyType.Ghost, eLogMoneyType.GhostOpenBoxCost)) {
                return GameErrorCode.E_BAG_ITEM_NO_ENOUGH;
            }
        }

        // 加奖励
        OpenGoodsBagResult randomGoods = GoodsBagMgr.getRandomGoods(boxItemId);
        player.getModule(CurrencyModule.class).addCurrency(randomGoods.getReward(), eLogMoneyType.Ghost, eLogMoneyType.GhostOpenBoxReward);

        // 完成事件
        userData.setComplete(true);

        GhostActivityProto.HandleBoxEventRespMsg.Builder builder = GhostActivityProto.HandleBoxEventRespMsg.newBuilder();
        builder.setRet(0);
        builder.setReward(PropertyHelper.parsePropertyToString(randomGoods.getReward()));
        player.sendPacket(ClientProtocol.U_GHOST_HANDLE_BOX_EVENT, builder);


        // 日志
        AutoLogMgr.add(new LogGhostBox(
                ghostConfig.getActivityId(),
                player.getUserId(),
                boxItemId,
                openCost,
                true,
                PropertyHelper.parsePropertyToString(randomGoods.getReward())
        ));

        return 0;
    }

    public int handleBoxEventFromCross(int ret,int boxId) {

        GhostConfig ghostConfig = GhostMgr.getGhostConfig();
        int boxItemId = boxId;
        String openCost = "";
        for (GhostBoxConfig boxConfig : ghostConfig.getBoxConfigList()) {
            if (boxItemId == boxConfig.getBoxItemId()) {
                openCost = boxConfig.getOpenCost();
                break;
            }
        }

        // 扣道具
        if (!openCost.equals("0")) {
            player.getModule(PreReduceModule.class).restorePreReduce(openCost);
        }
        if(ret == 0){
            if (!openCost.equals("0")){
                Property costProp = PropertyHelper.parseStringToProperty(openCost);
                if (!player.getModule(CurrencyModule.class).removeCurrency(costProp, eLogMoneyType.Ghost, eLogMoneyType.GhostOpenBoxCost)) {
                    //不可能啊草
                    return GameErrorCode.E_BAG_ITEM_NO_ENOUGH;
                }
            }
        }else{
            return ret;
        }
        // 加奖励
        OpenGoodsBagResult randomGoods = GoodsBagMgr.getRandomGoods(boxItemId);
        player.getModule(CurrencyModule.class).addCurrency(randomGoods.getReward(), eLogMoneyType.Ghost, eLogMoneyType.GhostOpenBoxReward);

        GhostActivityProto.HandleBoxEventRespMsg.Builder builder = GhostActivityProto.HandleBoxEventRespMsg.newBuilder();
        builder.setRet(0);
        builder.setReward(PropertyHelper.parsePropertyToString(randomGoods.getReward()));
        player.sendPacket(ClientProtocol.U_GHOST_HANDLE_BOX_EVENT, builder);

        // 日志
        AutoLogMgr.add(new LogGhostBox(
                ghostConfig.getActivityId(),
                player.getUserId(),
                boxItemId,
                openCost,
                true,
                PropertyHelper.parsePropertyToString(randomGoods.getReward())
        ));

        return 0;
    }

    //商会宝箱跨服来开
    public int handleBoxEventToCross(int boxId) {
        String unionUid = player.getUserInfo().getUnionUid();
        if (StringUtils.isNullOrEmpty(unionUid)) {
            return GameErrorCode.E_GHOST_ACTIVITY_NO_UNION;
        }
        GhostConfig ghostConfig = GhostMgr.getGhostConfig();

        int boxItemId = boxId;

        String openCost = "";
        for (GhostBoxConfig boxConfig : ghostConfig.getBoxConfigList()) {
            if (boxItemId == boxConfig.getBoxItemId()) {
                openCost = boxConfig.getOpenCost();
                break;
            }
        }
        if (StringUtils.isNullOrEmpty(openCost)) {
            log.error("GhostModule open box error! can not find cost! had skip event! userId={}, eventParam={}", player.getUserId(), userData.getParam());
            userData.setComplete(true);
            return GameErrorCode.E_GHOST_ACTIVITY_EVENT_HAD_COMPLETE;
        }

        // 扣道具
        if (!openCost.equals("0")) {
            Property costProp = PropertyHelper.parseStringToProperty(openCost);
            if (!player.getModule(CurrencyModule.class).currencyIsEnough(costProp)) {
                return GameErrorCode.E_BAG_ITEM_NO_ENOUGH;
            }
            player.getModule(PreReduceModule.class).preReduce(openCost);
        }



        GhostActivityProto.CrossHandleBoxReqMsg.Builder builder = GhostActivityProto.CrossHandleBoxReqMsg.newBuilder();
        builder.setActivityId(GhostMgr.getActivityId());
        builder.setBoxId(boxId);
        builder.setUnionId(unionUid);
        player.sendPacket(CrossProtocol.C2_GHOST_ACTIVITY_HANDLE_BOX_EVENT, builder);
        return 0;
    }

    /**
     * 处理闷包事件
     */
    public int handleGuessEvent() {

        if (userData == null) {
            return GameErrorCode.E_GHOST_ACTIVITY_NO_UNLOCK;
        }
        if (userData.isComplete()) {
            return GameErrorCode.E_GHOST_ACTIVITY_EVENT_HAD_COMPLETE;
        }
        if (userData.getEventType() != 3) {
            return GameErrorCode.E_GHOST_ACTIVITY_EVENT_ERROR;
        }

        GhostConfig config = GhostMgr.getGhostConfig();
        Property cost = PropertyHelper.parseStringToProperty(config.getGuessCost());

        // 扣消耗
        if (!player.getModule(CurrencyModule.class).removeCurrency(cost, eLogMoneyType.Ghost, eLogMoneyType.GhostGuessCost)) {
            return GameErrorCode.E_GHOST_ACTIVITY_ITEM_NO_ENOUGH;
        }

        // 加奖励
        boolean real = new Random().nextInt(1000) < config.getGuessRealRatio();
        List<String> rewardList = StringUtils.stringToStringList(userData.getParam(), "\\|");
        String reward = rewardList.get(real ? 0 : 1);
        player.getModule(CurrencyModule.class).addCurrency(PropertyHelper.parseStringToProperty(reward), eLogMoneyType.Ghost, eLogMoneyType.GhostGuessReward);

        userData.setComplete(true);

        GhostActivityProto.HandleGuessEventRespMsg.Builder builder = GhostActivityProto.HandleGuessEventRespMsg.newBuilder();
        builder.setRet(0);
        builder.setIsReal(real);
        builder.setReward(reward);
        builder.setOtherReward(rewardList.get(real ? 1 : 0));
        player.sendPacket(ClientProtocol.U_GHOST_HANDLE_GUESS_EVENT, builder);

        AutoLogMgr.add(new LogGhostGuess(
                config.getActivityId(),
                player.getUserId(),
                userData.getParam(),
                true,
                real
        ));

        return 0;
    }

    /**
     * 攻击boss
     */
    public int attackBoss(int patronsId, int bossId, int attackTimes) {

        if (userData == null) {
            return GameErrorCode.E_GHOST_ACTIVITY_NO_UNLOCK;
        }

        GhostConfig config = GhostMgr.getGhostConfig();

        // 是否有门客判断
        Map<Integer, UserPatrons> userPatronsMap = player.getModule(PatronsModule.class).getUserPatronsMap();
        UserPatrons userPatrons = userPatronsMap.get(patronsId);
        if (userPatrons == null) {
            return GameErrorCode.E_GHOST_ACTIVITY_CAN_NOT_FIND_PATRONS;
        }

        // 获取门客攻击次数
        Map<Integer, GhostPatrons> attackMap = userData.getAttackMap();
        if (!attackMap.containsKey(patronsId)) {
            attackMap.put(patronsId, new GhostPatrons(patronsId, 0, 0));
            userData.setUpdateOption();
        }
        GhostPatrons ghostPatrons = attackMap.get(patronsId);

        // 攻击次数判断
        if (attackTimes == 0) { // 免费
            if (ghostPatrons.getFree() >= config.getFreeAttackTimes()) {
                return GameErrorCode.E_GHOST_ACTIVITY_FREE_ATTACK_TIMES_NO_ENOUGH;
            }
        } else { // 付费
            if (ghostPatrons.getFree() < config.getFreeAttackTimes()) {
                return GameErrorCode.E_GHOST_ACTIVITY_FREE_ATTACK_FIRST;
            }
            if (ghostPatrons.getCost() + 1 != attackTimes) {
                return GameErrorCode.E_GHOST_ACTIVITY_ATTACK_TIMES_ERROR;
            }
            if (config.getAttackCostItemCountList().size() < attackTimes) {
                return GameErrorCode.E_GHOST_ACTIVITY_ATTACK_TIMES_LIMIT;
            }
        }

        // 判断该门客上次攻击是否返回
        long now = System.currentTimeMillis();
        if (ghostPatrons.getCrossReqTime() + GameConfig.GHOST_ATTACK_WAIT_CROSS_TIME > now) {
            return GameErrorCode.E_GHOST_ACTIVITY_REQUEST_FREQUENTLY;
        }
        // 设置跨服请求时间
        ghostPatrons.setCrossReqTime(System.currentTimeMillis());

        // 预扣除消耗
        String cost = "";
        if (attackTimes > 0) {
            cost = config.getAttackCostItemId() + "=" + config.getAttackCostItemCountList().get(attackTimes - 1);
            Property property = PropertyHelper.parseStringToProperty(cost);
            if (!player.getModule(CurrencyModule.class).currencyIsEnough(property)) {
                return GameErrorCode.E_GHOST_ACTIVITY_ITEM_NO_ENOUGH;
            }
            player.getModule(PreReduceModule.class).preReduce(cost);
        }

        // 攻击力和buff
        long ability = userPatrons.getAbility().longValue();
        int buffAddition = GhostMgr.getAttackBuffAddition(userData.getBuffLevel());
        int talentAddition = 0;
        for (UserPatrons patrons : userPatronsMap.values()) {
            for (UserPatronsSkill patronsSkill : patrons.getSkillList()) {
                if (patronsSkill.getType() != ePatronsSkillType.Talent.getValue()) {
                    continue;
                }
                SkillInfo skillInfo = SkillMgr.getSkillInfo(patronsSkill.getSkillId());
                if (skillInfo.getType() == eSkillType.GhostTalentAttackAddition.getValue()) {
                    talentAddition += SkillMgr.getSkillAddition(skillInfo, patronsSkill.getSkillLv());
                }
            }
        }

        long curioAddition = CurioMgr.getSkillAdditionBySkillType(eSkillType.GhostPatronsSkill.getValue(), player, 0);

        talentAddition += curioAddition;

        // 进入房间
        GhostSceneLogic.enterRoom(player, bossId);

        // 发跨服
        GhostActivityProto.CrossAttackBossReqMsg.Builder builder = GhostActivityProto.CrossAttackBossReqMsg.newBuilder();
        builder.setActivityId(config.getActivityId());
        builder.setServerId(player.getUserInfo().getOriginalServerId());
        builder.setPatronsId(patronsId);
        builder.setCost(cost);
        builder.setBossId(bossId);
        builder.setAbility(ability);
        builder.setBuffAddition(buffAddition);
        builder.setTalentAddition(talentAddition);
        builder.setAttackTimes(attackTimes);
        builder.setPlayerInfo(PlayerPb.parsePlayerBaseTempMsg(player.getUserInfo()));
        String unionUid = player.getUserInfo().getUnionUid();
        if (!StringUtils.isNullOrEmpty(unionUid)) {
            builder.setUnionUid(unionUid);
        }
        builder.setUserResetTime(userData.getResetTime());
        player.sendPacket(CrossProtocol.C2_GHOST_ACTIVITY_ATTACK_BOSS, builder);
        return 0;
    }

    public int getUnionChest(int activityId) {
        GhostActivityProto.CrossGetGhostUnionChestDataReqMsg.Builder builder = GhostActivityProto.CrossGetGhostUnionChestDataReqMsg.newBuilder();
        builder.setActivityId(activityId);
        String unionUid = player.getUserInfo().getUnionUid();
        if (!StringUtils.isNullOrEmpty(unionUid)) {
            builder.setUnionUid(unionUid);
        }else{
            return GameErrorCode.E_GHOST_ACTIVITY_NO_UNION;
        }
        player.sendPacket(CrossProtocol.C2_GHOST_ACTIVITY_GET_UNION_CHEST, builder);
        return 0;
    }

    /**
     * 跨服攻击boss返回
     */
    public int attackBossFromCross(int ret, int patronsId, String cost, int attackTimes, long realDamage,
                                   GhostActivityProto.GhostBossDataMsg bossDataMsg, boolean kill, String stageReward, long userResetTime) {

        if (!userData.getAttackMap().containsKey(patronsId)) {
            userData.getAttackMap().put(patronsId, new GhostPatrons(patronsId, 0, 0));
            userData.setUpdateOption();
        }
        GhostPatrons ghostPatrons = userData.getAttackMap().get(patronsId);

        // 清空请求时间
        ghostPatrons.setCrossReqTime(0);

        // 返还预扣除
        if (!StringUtils.isNullOrEmpty(cost)) {
            player.getModule(PreReduceModule.class).restorePreReduce(cost);
        }

        if (ret != 0) {
            return ret;
        }

        if (userData.getResetTime() != userResetTime) {
            return GameErrorCode.E_GHOST_ACTIVITY_REFRESH;
        }

        // 扣次数
        if (attackTimes > 0) {
            ghostPatrons.setCost(ghostPatrons.getCost() + 1);
            userData.setUpdateOption();
        } else {
            ghostPatrons.setFree(ghostPatrons.getFree() + 1);
            userData.setUpdateOption();
        }

        // 扣消耗
        Property costProp = PropertyHelper.parseStringToProperty(cost);
        player.getModule(CurrencyModule.class).removeCurrency(costProp, eLogMoneyType.Ghost, eLogMoneyType.GhostAttackBossCost);

        GhostConfig ghostConfig = GhostMgr.getGhostConfig();

        // 组装奖励
        Property reward = new Property();

        // 加阶段奖励
        Property stage = PropertyHelper.parseStringToProperty(stageReward);
        if (stage != null) {
            reward.addProperty(stage);

            // 上公告
            WorldMessageProto.WorldMessageTempMsg.Builder msg = WorldMessagePb.parseWorldMessageTempMsg(
                    player.getUserInfo(), eMessageType.GhostDamageBigBossMsg.getValue(), eChatContentType.Common.getContentType(), bossDataMsg.getBossType() + "|" + stageReward,
                    System.currentTimeMillis(), ghostConfig.getActivityId(), null);
            WorldMessageMgr.sendCrossActivityChat(msg);
        }

        // （积分数量 = 实际伤害 x 配置的比例 x 开服天数加成）
        long scoreCount = BigDecimal.valueOf(realDamage)
                .multiply(BigDecimal.valueOf(ghostConfig.getDamageToScoreRatioList().get(0)))
                .multiply(BigDecimal.valueOf(GhostMgr.getScoreDayAddition()))
                .divide(BigDecimal.valueOf(ghostConfig.getDamageToScoreRatioList().get(1)), 0, BigDecimal.ROUND_UP).longValue();
        reward.addProperty(ghostConfig.getScoreId(), BigInteger.valueOf(scoreCount));
        // （鬼市信物数量 = 1.免费固定数量 2.付费出战消耗道具数量 * 配置的比例）
        int tokenCount = ghostConfig.getFreeAttackGetTokenCount();
        if (attackTimes > 0) {
            int costCount = costProp == null ? 0 : costProp.getCountByGoodsId(ghostConfig.getAttackCostItemId()).intValue();
            tokenCount = BigDecimal.valueOf(costCount)
                    .multiply(BigDecimal.valueOf(ghostConfig.getAttackCostToTokenCoefficient())).divide(BigDecimal.valueOf(1000), 0, BigDecimal.ROUND_UP).intValue();
        }
        // （判断击杀奖励）
        if (kill) {
            for (GhostBossConfig bossConfig : ghostConfig.getBossConfigList()) {
                if (bossConfig.getBossType() == bossDataMsg.getBossType()) {
                    // （固定奖励）
                    reward.addProperty(PropertyHelper.parseStringToProperty(bossConfig.getRewards()));
                    // （固定积分奖励 x 开服天数加成）
                    BigInteger score = BigDecimal.valueOf(bossDataMsg.getTotalHp())
                            .multiply(BigDecimal.valueOf(ghostConfig.getDamageToScoreRatioList().get(0)))
                            .multiply(BigDecimal.valueOf(bossConfig.getRewardsKill()))
                            .multiply(BigDecimal.valueOf(GhostMgr.getScoreDayAddition()))
                            .divide(BigDecimal.valueOf(ghostConfig.getDamageToScoreRatioList().get(1)), 4, BigDecimal.ROUND_UP)
                            .divide(BigDecimal.valueOf(1000), 0, BigDecimal.ROUND_UP).toBigInteger();
                    reward.addProperty(ghostConfig.getScoreId(), score);
                    // （随机奖励）
                    Random random = new Random();
                    int index = RandomHelper.getRandomIndexByWeight(bossConfig.getRandomWeightList(), random);
                    reward.addProperty(PropertyHelper.parseStringToProperty(bossConfig.getRandomRewardList().get(index)));
                    // 上公告（击杀的发：boss类型）
                    if (bossConfig.isNotice()) {
                        WorldMessageProto.WorldMessageTempMsg.Builder msg = WorldMessagePb.parseWorldMessageTempMsg(
                                player.getUserInfo(), eMessageType.GhostKillBossMsg.getValue(), eChatContentType.Common.getContentType(), bossDataMsg.getBossType() + "",
                                System.currentTimeMillis(), ghostConfig.getActivityId(), null);
                        WorldMessageMgr.sendCrossActivityChat(msg);
                    }
                    break;
                }
            }
        }

        // 加奖励
        player.getModule(CurrencyModule.class).addCurrency(reward, eLogMoneyType.Ghost, eLogMoneyType.GhostAttackBossReward);
        userData.setScore(userData.getScore() + reward.getCountByGoodsId(ghostConfig.getScoreId()).intValue());
        userData.setTokenCount(userData.getTokenCount() + tokenCount);
        // 榜单变化
        player.notifyListener(eGamePlayerEventType.GhostScoreRank.getValue(), userData.getScore());
        player.notifyListener(eGamePlayerEventType.GhostTokenCount.getValue(), userData.getTokenCount());
        player.notifyListener(eGamePlayerEventType.GhostUnionScoreRank.getValue(),
                new UnionRiseRankArgs(UnionRiseRankArgs.NOTIFY_TYPE_NORMAL, BigInteger.valueOf(userData.getScore()), player.getUserInfo().getUnionUid()));

        ActivityInfo activityInfo = GhostMgr.getActivityInfo();
        if(activityInfo != null) {
            SeasonTaskConditionData data = new SeasonTaskConditionData(BigInteger.valueOf((long) activityInfo.getType()), BigInteger.ONE);
            player.notifyListener(eGamePlayerEventType.GhostDispatchTask.getValue(), data);
        }

        // 鬼市信物不入背包，但要给客户端看
        reward.addProperty(ghostConfig.getTokenId(), BigInteger.valueOf(tokenCount));
        // 返回
        GhostActivityProto.AttackBossRespMsg.Builder builder = GhostActivityProto.AttackBossRespMsg.newBuilder();
        builder.setRet(ret);
        builder.setReward(PropertyHelper.parsePropertyToString(reward));
        builder.setBossData(bossDataMsg);
        builder.setRealDamage(realDamage);
        player.sendPacket(ClientProtocol.U_GHOST_ATTACK_BOSS, builder);


        // 日志
        AutoLogMgr.add(new LogGhostAttack(
                ghostConfig.getActivityId(),
                player.getUserId(),
                -1, // 这个参数不用了，没实际意义
                bossDataMsg.getBossId() + "|" + bossDataMsg.getBossType(),
                patronsId,
                realDamage,
                kill,
                PropertyHelper.parsePropertyToString(reward)
        ));

        // 日志
        AutoLogMgr.add(new LogGhostToken(
                ghostConfig.getActivityId(),
                player.getUserId(),
                tokenCount,
                userData.getTokenCount()
        ));

        //珍兽绑定 鱼类绑定
        player.getModule(VehicleModule.class).bindPatrons(patronsId, ghostConfig.getActivityId());

        return 0;
    }

    /**
     * 领取鬼市送财奖励
     */
    public int getDisperseReward(int type) {
        if (userData == null) {
            return GameErrorCode.E_GHOST_ACTIVITY_NO_UNLOCK;
        }

        if (type == 1 && userData.isGetDisperse()) {
            return GameErrorCode.E_GHOST_ACTIVITY_ALREADY_GET_DISPERSE_REWARD;
        } else if (type == 2 && userData.isGetCleanDisperse()) {
            return GameErrorCode.E_GHOST_ACTIVITY_ALREADY_GET_DISPERSE_REWARD;
        }

        GhostConfig ghostConfig = GhostMgr.getGhostConfig();

        GhostActivityProto.CrossGetDisperseGoldRewardReqMsg.Builder builder = GhostActivityProto.CrossGetDisperseGoldRewardReqMsg.newBuilder();
        builder.setActivityId(ghostConfig.getActivityId());
        builder.setServerId(player.getUserInfo().getOriginalServerId());
        builder.setType(type);
        builder.setUserResetTime(userData.getResetTime());
        player.sendPacket(CrossProtocol.C2_GHOST_ACTIVITY_GET_DISPERSE_REWARD, builder);
        return 0;
    }

    /**
     * 领取鬼市送财奖励跨服返回
     */
    public int getDisperseRewardFromCross(String randomReward, boolean isNotice, boolean isSpec, int type, long userResetTime) {
        if (userData == null) {
            return GameErrorCode.E_GHOST_ACTIVITY_NO_UNLOCK;
        }
        if (type == 1 && userData.isGetDisperse()
                || type == 2 && userData.isGetCleanDisperse()) {
            return GameErrorCode.E_GHOST_ACTIVITY_ALREADY_GET_DISPERSE_REWARD;
        }

        if (userResetTime != userData.getResetTime()) {
            return GameErrorCode.E_GHOST_ACTIVITY_REFRESH;
        }

        GhostConfig config = GhostMgr.getGhostConfig();
        if (config == null) {
            return GameErrorCode.E_GHOST_ACTIVITY_NO_OPEN;
        }

        // 送财奖励 = 随机道具奖励 + 固定元宝奖励
        Property finalReward = StringUtils.isNullOrEmpty(randomReward) ? new Property() : PropertyHelper.parseStringToProperty(randomReward);
        if (type == 1) {
            finalReward.addProperty(PropertyHelper.parseStringToProperty(config.getDisperseBaseReward()));
        } else {
            finalReward.addProperty(PropertyHelper.parseStringToProperty(config.getDisperseBaseReward2()));
        }

        // 加奖励
        if (type == 1) {
            userData.setGetDisperse(true);
        } else {
            userData.setGetCleanDisperse(true);
        }
        player.getModule(CurrencyModule.class).addCurrency(finalReward, eLogMoneyType.Ghost, eLogMoneyType.GhostDisperseReward);

        // 上公告（送财的发：boss类型|奖励）
        if (type == 1) {
            if (isSpec) {
                WorldMessageProto.WorldMessageTempMsg.Builder msg = WorldMessagePb.parseWorldMessageTempMsg(
                        player.getUserInfo(), eMessageType.GhostFindBossMsg.getValue(),  eChatContentType.Common.getContentType(),GhostMgr.getBigBossType() + "|" + randomReward,
                        System.currentTimeMillis(), config.getActivityId(), null);
                WorldMessageMgr.sendCrossActivityChat(msg);
            } else if (isNotice) {
                WorldMessageProto.WorldMessageTempMsg.Builder msg = WorldMessagePb.parseWorldMessageTempMsg(
                        player.getUserInfo(), eMessageType.GhostDisperseMsg.getValue(), eChatContentType.Common.getContentType(),GhostMgr.getBigBossType() + "|" + randomReward,
                        System.currentTimeMillis(), config.getActivityId(), null);
                WorldMessageMgr.sendCrossActivityChat(msg);
            }
        }

        GhostActivityProto.GetDisperseGoldRewardRespMsg.Builder builder = GhostActivityProto.GetDisperseGoldRewardRespMsg.newBuilder();
        builder.setRet(0);
        builder.setReward(PropertyHelper.parsePropertyToString(finalReward));
        player.sendPacket(ClientProtocol.U_GHOST_GET_DISPERSE_REWARD, builder);

        // 日志
        AutoLogMgr.add(new LogGhostDisperse(
                config.getActivityId(),
                player.getUserId(),
                type,
                isSpec,
                PropertyHelper.parsePropertyToString(finalReward)
        ));

        return 0;
    }
}
